	import javax.swing.*;
	import java.awt.event.*;
	import java.awt.*;
	import java.util.*;
	import com.mxgraph.swing.mxGraphComponent;
    import com.mxgraph.view.mxGraph;
    import com.mxgraph.util.*;





	public class Mainframe extends JFrame implements ActionListener
	{
		
		Container c = getContentPane();
	
		JButton addCellButton;
		JButton colorButton;
		JButton addMobile;
		JButton moveMobile;
		JButton callMobile;
		
		//field for source of a transaction
		JTextField sourceField;
		//field of destination of a transaction
		JTextField destField;
		//field to contain number of cells to add
		JTextField numCellsField;
		//field for point forwarding level
		JTextField forewardingField;
		
		JRadioButton addressRad;
		JRadioButton pointerRad;
		JRadioButton forewardRad;
		JRadioButton replicRad;
		
		int  xOff, yOff = 0; 
		//current amount of cells
        int numCells;
        //current amount of mobile users
        int numMobile;
        //array of Cell nodes
        Object [] arrCellsDraw;
        //array of Mobile user nodes
        Object [] arrMobileDraw;
        
        Node []arrCells;
        ArrayList<MobileUser> arrMobile;
        mxGraph graph;
 
        Object parent;
        JLabel sourceLabel;
        JLabel destLabel;
        
        
        //contains output of transactions, like cost, current action, etc
        JTextArea outpArea;
        
        //current transaction method;
        public TransType currentTrans;
        
        
       //JTextArea to hold output of operations
     
		/** Initialization method */ 
		public Mainframe()
	   {
			super("Mobile Locator");
			numCells = 0;
			numMobile = 0;
			getContentPane().setLayout(new BorderLayout());
			graph = new mxGraph();
			parent = graph.getDefaultParent();
			
			//initialize buttons and JtextAreas
			addCellButton = new JButton("Add Cell");
			colorButton = new JButton("colorRed");
			addMobile = new JButton("add Mobile User");
			moveMobile = new JButton("move Mobile User");
			callMobile = new JButton("Call mobile User");
			sourceField = new JTextField(5);
			destField = new JTextField(5);
			numCellsField = new JTextField(5);
			forewardingField = new JTextField(5);
		   
		    sourceLabel = new JLabel("Source");
			destLabel = new JLabel("Destination");
			
			
			
			addressRad = new JRadioButton("Explicit Address");
			pointerRad = new JRadioButton("Pointer Address");
			forewardRad = new JRadioButton("Pointer Forewarding");
			replicRad = new JRadioButton("Replication");
			
			ButtonGroup modeSelect = new ButtonGroup();
			
			modeSelect.add(addressRad);
			modeSelect.add(pointerRad);
			modeSelect.add(forewardRad);
			modeSelect.add(replicRad);
			
			outpArea = new JTextArea(15,15);
			arrCellsDraw = new Object[50];
		    arrMobileDraw = new Object[50];
		    arrCells = new Node[50];
		    arrMobile = new  ArrayList<MobileUser> ();
		    //create the root node
			graph.getModel().beginUpdate();
			arrCells[numCells] = new Node(arrCells, outpArea,arrMobile);
			
			try
			{
				
				arrCellsDraw[0]  = graph.insertVertex(parent, null, "0", 500, 20, 30,
						30);
			
			    
	
				
			}
			finally
			{
				graph.getModel().endUpdate();
			}
			numCells++;
			
			//takes input from destField and colors the cell with the corresponding
			//index red, just to test functionality of cell coloring
			colorButton.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					int coloredCellId = Integer.parseInt(destField.getText());
					
				    colorRed( coloredCellId);
				
				
				}
				
				
			});
		    //takes input from destfield as the parent of a set of children
			//takes input from numCellsField as the number of children to add
			//calls addChildren with these inputs
			addCellButton.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					int parentCell = Integer.parseInt(destField.getText());
					int numChildren = Integer.parseInt(numCellsField.getText());
					addChildren(parentCell, numChildren);
				
				}
				
				
			});
			//takes input from destField as the cell containing a new Mobile Agent
			//takes input from SourceField as the name of the new mobile agent
			//calls insertMU on these inputs
			addMobile.addActionListener(new ActionListener()
			{
			
				public void actionPerformed(ActionEvent e)
				{
					
					int destinationCell = Integer.parseInt(destField.getText());
					
					String muId = sourceField.getText();
					insertMU(muId, destinationCell);
					
				}
				
				
			});
			//takes input from source field as the name of the Mobile User to move
			//takes input from destField as the cell to move the mobile unit to
			//calls moveMU with these inputs
			moveMobile.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					int destinationCell = Integer.parseInt(destField.getText());
					String muId = (sourceField.getText());
					moveMu(muId, destinationCell);
				}
			});
			callMobile.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					
					String sourceId = (sourceField.getText());
					String destId = (destField.getText());
					callMobile(sourceId, destId);
				}
				
				
			});
			addressRad.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					currentTrans = TransType.ADDRESS;
					updateTrans();
				}
				
			});
			pointerRad.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					currentTrans = TransType.POINTER;
					updateTrans();
				}
				
			});
			forewardRad.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					currentTrans = TransType.FOREWARD;
					updateTrans();
				}
				
			});
			replicRad.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					currentTrans = TransType.REPLICATION;
					updateTrans();
				}
				
			});
			//adds the command elements to the CommandPanel
			JPanel CommandPanel = new JPanel();
			CommandPanel.setLayout(new GridLayout(0,6));
			CommandPanel.add(destLabel);
			CommandPanel.add(destField);
			CommandPanel.add(sourceLabel);
			CommandPanel.add(sourceField);
			CommandPanel.add(new JLabel("number of Children"));
			CommandPanel.add(numCellsField);
			CommandPanel.add(addCellButton);
			CommandPanel.add(colorButton);
			CommandPanel.add(addMobile);
			CommandPanel.add(moveMobile);
			CommandPanel.add(callMobile);
			
			JPanel SelectOutput = new JPanel();
			SelectOutput.setLayout(new GridLayout(0,1));
			SelectOutput.add(addressRad);
			SelectOutput.add(pointerRad);
			SelectOutput.add(forewardRad);
			SelectOutput.add(replicRad);
			
			JScrollPane outpScrollpane = new JScrollPane(outpArea);
			mxGraphComponent graphComponent = new mxGraphComponent(graph);
			getContentPane().add(graphComponent, BorderLayout.CENTER);
			getContentPane().add(CommandPanel, BorderLayout.NORTH);
			getContentPane().add(SelectOutput, BorderLayout.EAST);
			
			getContentPane().add(outpScrollpane, BorderLayout.SOUTH);
			
	   }
		
		@Override
		public void actionPerformed(ActionEvent arg0) {
			// TODO Auto-generated method stub
			
		}
		//takes the index value of the parentCell and number of children to add
		//adds that amount of children to the parent cell
		public void addChildren(int parentCell, int numChildren)
		{
			Object Cellparent = arrCellsDraw[parentCell];
			mxRectangle myRec = graph.getBoundingBox(Cellparent );
			double parentX = myRec.getCenterX();
			double parentY = myRec.getCenterY();
			double offsetX = -125;
			double offsetY = 100;
			for(int i = 0; i < numChildren; i++)
			{
				graph.getModel().beginUpdate();
				try
				{
					arrCells[numCells] = new Node(arrCells[parentCell], numCells, arrCells,outpArea,arrMobile);
					arrCells[parentCell].addChild(arrCells[numCells]);
					arrCellsDraw[numCells]  = graph.insertVertex(parent, null, Integer.toString(numCells), parentX+offsetX, parentY
							+offsetY, 40, 30);
					offsetX += 375.0/ numChildren;
					graph.insertEdge(parent, null, null, Cellparent, arrCellsDraw[numCells]);
					numCells++;
					
				}
				finally
				{
					graph.getModel().endUpdate();
					
				}
				graph.refresh();
				
			}
		}
		//colors the cell with the given index red
		public void colorRed(int cellId)
		{
			Object myCell = arrCellsDraw[cellId];
			graph.getModel().beginUpdate();
			try
			{
				graph.setCellStyles(mxConstants.STYLE_FILLCOLOR,"red", new Object[]{myCell});
			}
			finally
			{
				graph.getModel().endUpdate();
			}
			graph.refresh();	
		}
		//resets all cells to blue
		public void resetColors()
		{
			graph.getModel().beginUpdate();
			try
			{
				graph.setCellStyles(mxConstants.STYLE_FILLCOLOR,"gray", arrCellsDraw);
			}
			finally
			{
				graph.getModel().endUpdate();
			}
			graph.refresh();	
			
		}
		//inserts a mobile unit with an id of Id and inserts it on a 
		//cell with an index of destinationCell
		public void insertMU(String Id, int destinationCell)
		{
			deactivateAll();
			arrMobile.add(new MobileUser(arrCells[destinationCell], Id));
			
			Object containingCell = arrCellsDraw[destinationCell];
			graph.getModel().beginUpdate();
			try
			{
				
				mxRectangle myRec = graph.getBoundingBox(containingCell );
				double parentX = myRec.getCenterX();
				double parentY = myRec.getCenterY();
				arrMobileDraw[numMobile] = graph.insertVertex(parent, null, Id, parentX , parentY , 20, 20);
				numMobile++;
				
			}
			
			finally
			{
				graph.getModel().endUpdate();
			}
		
			colorActive();
			graph.refresh();
			
		}
		//moves mobile unit with Id to the cell with the index of destIndex
		public void moveMu(String Id,  int DestinationCellId)
		{
			deactivateAll();
			Object DestinationCellDraw = arrCellsDraw[DestinationCellId];
			
			int index = 0;
			
			for(int i = 0; i < numMobile; i++)
			{  if(arrMobile.get(i).getId().equals(Id))
				{
					arrMobile.get(i).move(DestinationCellId);
					arrMobile.get(i).move(arrCells[DestinationCellId]);
				
				}
				if(graph.getLabel(arrMobileDraw[i]).equals(Id))
						{
							index = i;
					
						}
				
				
			}
		 
			graph.getModel().beginUpdate();
			try
			{
				mxRectangle myRec = graph.getBoundingBox(DestinationCellDraw );
				double parentX = myRec.getCenterX();
				double parentY = myRec.getCenterY();
				graph.removeCells(new Object[]{arrMobileDraw[index]});
		        arrMobileDraw[index] = graph.insertVertex(parent, null, Id, parentX , parentY , 20, 20);
			
			}
			finally
			{
				graph.getModel().endUpdate();
			}
			colorActive();
			graph.refresh();
			
		}
		public void callMobile(String sourceId, String destId)
		{
			deactivateAll();
			for(int i = 0; i < numMobile; i++)
			{  if(arrMobile.get(i).getId().equals(sourceId))
				{
					arrMobile.get(i).sendCall(destId);
				
				}
		
			}
			colorActive();
		
		}
		public void deactivateAll()
		{
			resetColors();
			for(int i = 0; i < numCells; i++)
			{
				arrCells[i].deactivate();
			}
			
		}
		public void colorActive()
		{
			for(int i = 0; i < numCells; i++)
			{
				if(arrCells[i].getActive() == true)
				{
					colorRed(i);
				}
				
			}
			
		}
		public void updateTrans()
		{
			for(int i = 0; i < numCells; i++)
			{
				arrCells[i].setTransType(currentTrans);
				
			}
			for(int i = 0; i < arrMobile.size(); i++)
			{
				arrMobile.get(i).changeTransType(currentTrans);
				
			}
			
		}
	}


